package com.castle.fortress.admin.study.exam.controller;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.castle.fortress.admin.core.annotation.CastleLog;
import com.castle.fortress.admin.core.constants.GlobalConstants;
import com.castle.fortress.admin.member.dto.MemberAuthorityDto;
import com.castle.fortress.admin.member.entity.MemberAuthorityEntity;
import com.castle.fortress.admin.member.service.MemberAuthorityService;
import com.castle.fortress.admin.study.exam.dto.StudyExamDto;
import com.castle.fortress.admin.study.exam.dto.StudyExamQuestionDto;
import com.castle.fortress.admin.study.exam.entity.StudyExamEntity;
import com.castle.fortress.admin.study.exam.entity.StudyExamQuestionEntity;
import com.castle.fortress.admin.study.exam.service.StudyExamQuestionService;
import com.castle.fortress.admin.study.exam.service.StudyExamService;
import com.castle.fortress.admin.system.entity.SysUser;
import com.castle.fortress.admin.utils.ExcelUtils;
import com.castle.fortress.admin.utils.WebUtil;
import com.castle.fortress.common.entity.DynamicExcelEntity;
import com.castle.fortress.common.entity.RespBody;
import com.castle.fortress.common.enums.AuthorityTypeEnum;
import com.castle.fortress.common.enums.ExamStatusEnum;
import com.castle.fortress.common.enums.OperationTypeEnum;
import com.castle.fortress.common.exception.BizException;
import com.castle.fortress.common.respcode.BizErrorCode;
import com.castle.fortress.common.respcode.GlobalRespCode;
import com.castle.fortress.common.utils.ConvertUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 试卷管理 控制器
 *
 * @author castle
 * @since 2023-02-10
 */
@Api(tags="试卷管理管理控制器")
@Controller
public class StudyExamController {
    @Autowired
    private StudyExamService studyExamService;
    @Autowired
    private MemberAuthorityService memberAuthorityService;
    @Autowired
    private StudyExamQuestionService studyExamQuestionService;

    /**
     * 试卷管理的分页展示
     * @param studyExamDto 试卷管理实体类
     * @param current 当前页
     * @param size  每页记录数
     * @return
     */
    @CastleLog(operLocation="试卷管理",operType = OperationTypeEnum.QUERY)
    @ApiOperation("试卷管理分页展示")
    @GetMapping("/study/exam/studyExam/page")
    @ResponseBody
    @RequiresPermissions("study:exam:studyExam:pageList")
    public RespBody<IPage<StudyExamDto>> pageStudyExam(StudyExamDto studyExamDto, @RequestParam(required = false) Integer current, @RequestParam(required = false)Integer size){
        Integer pageIndex= current==null? GlobalConstants.DEFAULT_PAGE_INDEX:current;
        Integer pageSize= size==null? GlobalConstants.DEFAULT_PAGE_SIZE:size;
        Page<StudyExamDto> page = new Page(pageIndex, pageSize);
        IPage<StudyExamDto> pages = studyExamService.pageStudyExamExtends(page, studyExamDto);

        return RespBody.data(pages);
    }

    /**
     * 试卷管理的列表展示
     * @param studyExamDto 试卷管理实体类
     * @return
     */
    @CastleLog(operLocation="试卷管理",operType = OperationTypeEnum.QUERY)
    @ApiOperation("试卷管理列表展示")
    @GetMapping("/study/exam/studyExam/list")
    @ResponseBody
    public RespBody<List<StudyExamDto>> listStudyExam(StudyExamDto studyExamDto){
        List<StudyExamDto> list = studyExamService.listStudyExam(studyExamDto);
        return RespBody.data(list);
    }

    /**
     * 试卷管理保存
     * @param studyExamDto 试卷管理实体类
     * @return
     */
    @CastleLog(operLocation="试卷管理",operType = OperationTypeEnum.INSERT)
    @ApiOperation("试卷管理保存")
    @PostMapping("/study/exam/studyExam/save")
    @ResponseBody
    @RequiresPermissions("study:exam:studyExam:save")
    public RespBody<String> saveStudyExam(@RequestBody StudyExamDto studyExamDto){
        if(studyExamDto == null ){
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        if(studyExamDto.getExamQuestionDTOList() == null || studyExamDto.getExamQuestionDTOList().isEmpty()){
            throw new BizException(BizErrorCode.EXAM_QUESTIONS_BE_EMPTY);
        }
        StudyExamEntity studyExamEntity = ConvertUtil.transformObj(studyExamDto,StudyExamEntity.class);
        if(studyExamService.save(studyExamEntity)){
            //保存考试对象
            MemberAuthorityDto memberAuthorityDto = studyExamDto.getMemberAuthorityDto();
            memberAuthorityDto.setType(AuthorityTypeEnum.EXAM.getCode());
            memberAuthorityDto.setImposeId(studyExamEntity.getId());
            memberAuthorityService.save(ConvertUtil.transformObj(memberAuthorityDto, MemberAuthorityEntity.class));
            //保存考试题目
            List<StudyExamQuestionEntity> questionEntities = ConvertUtil.transformObjList(studyExamDto.getExamQuestionDTOList(),StudyExamQuestionEntity.class);
            for(StudyExamQuestionEntity entity:questionEntities){
                entity.setExamId(studyExamEntity.getId());
                entity.setQuestionId(entity.getId());
                entity.setId(null);
            }
            studyExamQuestionService.saveBatch(questionEntities);
            return RespBody.data("保存成功");
        }else{
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }

    /**
     * 试卷管理编辑
     * @param studyExamDto 试卷管理实体类
     * @return
     */
    @CastleLog(operLocation="试卷管理",operType = OperationTypeEnum.UPDATE)
    @ApiOperation("试卷管理编辑")
    @PostMapping("/study/exam/studyExam/edit")
    @ResponseBody
    @RequiresPermissions("study:exam:studyExam:edit")
    public RespBody<String> updateStudyExam(@RequestBody StudyExamDto studyExamDto){
        if(studyExamDto == null || studyExamDto.getId() == null || studyExamDto.getId().equals(0L)){
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        StudyExamEntity oldExam = studyExamService.getById(studyExamDto.getId());
        //草稿、未开始、定时发布 支持修改
        if(ExamStatusEnum.DRAFT.getCode().equals(oldExam.getStatus())
                ||ExamStatusEnum.NOT_START.getCode().equals(oldExam.getStatus())
                ||ExamStatusEnum.TIME_INTERVAL.getCode().equals(oldExam.getStatus())){
            if(ExamStatusEnum.NOT_START.getCode().equals(oldExam.getStatus()) && oldExam.getExamStartTime().compareTo(new Date()) == -1 ){
                throw new BizException(BizErrorCode.EXAM_STATUS_ERROR);
            }
            if(ExamStatusEnum.TIME_INTERVAL.getCode().equals(oldExam.getStatus()) && oldExam.getQuartzTime().compareTo(new Date()) == -1 && oldExam.getExamStartTime().compareTo(new Date()) ==-1){
                throw new BizException(BizErrorCode.EXAM_STATUS_ERROR);
            }
        }else{
            throw new BizException(BizErrorCode.EXAM_STATUS_ERROR);
        }
        if(studyExamDto.getExamQuestionDTOList() == null || studyExamDto.getExamQuestionDTOList().isEmpty()){
            throw new BizException(BizErrorCode.EXAM_QUESTIONS_BE_EMPTY);
        }
        StudyExamEntity studyExamEntity = ConvertUtil.transformObj(studyExamDto,StudyExamEntity.class);
        if(studyExamService.updateById(studyExamEntity)){
            //保存考试对象
            MemberAuthorityDto memberAuthorityDto = studyExamDto.getMemberAuthorityDto();
            if(memberAuthorityDto!=null && memberAuthorityDto.getId()!=null){
                memberAuthorityService.updateById(ConvertUtil.transformObj(memberAuthorityDto,MemberAuthorityEntity.class));
            }
            //修改考试题目
            studyExamQuestionService.deleteByExamId(studyExamEntity.getId());
            List<StudyExamQuestionEntity> questionEntities = ConvertUtil.transformObjList(studyExamDto.getExamQuestionDTOList(),StudyExamQuestionEntity.class);
            for(StudyExamQuestionEntity entity:questionEntities){
                entity.setExamId(studyExamEntity.getId());
                entity.setQuestionId(entity.getId());
                entity.setId(null);
            }
            studyExamQuestionService.saveBatch(questionEntities);
            return RespBody.data("保存成功");
        }else{
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }

    /**
     * 试卷管理删除
     * @param id
     * @return
     */
    @CastleLog(operLocation="试卷管理",operType = OperationTypeEnum.DELETE)
    @ApiOperation("试卷管理删除")
    @PostMapping("/study/exam/studyExam/delete")
    @ResponseBody
    @RequiresPermissions("study:exam:studyExam:delete")
    public RespBody<String> deleteStudyExam(@RequestParam Long id){
        if(id == null ){
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        if(studyExamService.removeById(id)) {
            QueryWrapper<MemberAuthorityEntity> authWrapper = new QueryWrapper<>();
            authWrapper.eq("type",AuthorityTypeEnum.EXAM.getCode());
            authWrapper.eq("impose_id",id);
            memberAuthorityService.remove(authWrapper);
            QueryWrapper<StudyExamQuestionEntity> examQuestionWrapper = new QueryWrapper<>();
            examQuestionWrapper.eq("exam_id",id);
            studyExamQuestionService.remove(examQuestionWrapper);
            //删除会员相关考试信息
            List<Long> ids = new ArrayList<>();
            ids.add(id);
            studyExamService.delExamMemberData(ids);
            return RespBody.data("保存成功");
        }else{
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }


    /**
     * 试卷管理批量删除
     * @param ids
     * @return
     */
    @CastleLog(operLocation="试卷管理",operType = OperationTypeEnum.DELETE)
    @ApiOperation("试卷管理批量删除")
    @PostMapping("/study/exam/studyExam/deleteBatch")
    @ResponseBody
    @RequiresPermissions("study:exam:studyExam:deleteBatch")
    public RespBody<String> deleteStudyExamBatch(@RequestBody List<Long> ids){
        if(ids == null || ids.size()<1){
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        if(studyExamService.removeByIds(ids)) {
            QueryWrapper<MemberAuthorityEntity> authWrapper = new QueryWrapper<>();
            authWrapper.eq("type",AuthorityTypeEnum.EXAM.getCode());
            authWrapper.in("impose_id",ids);
            memberAuthorityService.remove(authWrapper);
            QueryWrapper<StudyExamQuestionEntity> examQuestionWrapper = new QueryWrapper<>();
            examQuestionWrapper.in("exam_id",ids);
            studyExamQuestionService.remove(examQuestionWrapper);
            studyExamService.delExamMemberData(ids);
            return RespBody.data("保存成功");
        }else{
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }

    /**
     * 试卷管理详情
     * @param id 试卷管理id
     * @return
     */
    @CastleLog(operLocation="试卷管理",operType = OperationTypeEnum.QUERY)
    @ApiOperation("试卷管理详情")
    @GetMapping("/study/exam/studyExam/info")
    @ResponseBody
    @RequiresPermissions("study:exam:studyExam:info")
    public RespBody<StudyExamDto> infoStudyExam(@RequestParam Long id){
        SysUser sysUser = WebUtil.currentUser();
        if(sysUser==null){
            throw new BizException(GlobalRespCode.NO_LOGIN_ERROR);
        }
        if(id == null){
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        StudyExamDto studyExamDto =  studyExamService.getByIdExtends(id);
        //试题列表
        QueryWrapper<StudyExamQuestionEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("exam_id",id);
        List<StudyExamQuestionDto> examQuestionDTOS = ConvertUtil.transformObjList(studyExamQuestionService.list(wrapper),StudyExamQuestionDto.class);
        studyExamDto.setExamQuestionDTOList(examQuestionDTOS);
        //可见对象
        studyExamDto.setMemberAuthorityDto(memberAuthorityService.getByImposeId(AuthorityTypeEnum.EXAM.getCode(),id,sysUser));
        return RespBody.data(studyExamDto);
    }

	/**
     * 动态表头导出 依据展示的字段导出对应报表
     * @param dynamicExcelEntity
     * @param response
     * @throws Exception
     */
    @CastleLog(operLocation="试卷管理",operType = OperationTypeEnum.EXPORT)
	@PostMapping("/study/exam/studyExam/exportDynamic")
	@ApiOperation("动态表头导出，依据展示的字段导出对应报表")
	public void exportDynamic(@RequestBody DynamicExcelEntity<StudyExamDto> dynamicExcelEntity, HttpServletResponse response) throws Exception {
		List<StudyExamDto> list = studyExamService.listStudyExam(dynamicExcelEntity.getDto());
		//字典、枚举、接口、json常量等转义后的列表数据 根据实际情况初始化该对象，null为list数据直接导出
		List<List<Object>> dataList = null;
		/**
        * 根据实际情况初始化dataList,可参照 com.castle.fortress.admin.system.controller.TmpDemoController类中方法：exportDynamic
        */
		ExcelUtils.exportDynamic(response,dynamicExcelEntity.getFileName()+".xlsx",null,list,dynamicExcelEntity.getHeaderList(),dataList);
	}

    @CastleLog(operLocation="试卷管理",operType = OperationTypeEnum.UPDATE)
    @ApiOperation("获取可见范围")
    @PostMapping("/allocate")
    @ResponseBody
    @RequiresPermissions("study:exam:studyExam:allocate")
    public RespBody allocate(@RequestBody StudyExamDto dto){
        SysUser sysUser = WebUtil.currentUser();
        if(sysUser==null){
            throw new BizException(GlobalRespCode.NO_LOGIN_ERROR);
        }
        Map<String, Object> map=memberAuthorityService.scope(AuthorityTypeEnum.EXAM.getCode(),dto.getId(),sysUser);
        return RespBody.data(map);
    }


    @PostMapping("/earlyTermination")
    @ApiOperation("提前结束")
    @CastleLog(operLocation="试卷管理",operType = OperationTypeEnum.UPDATE)
    @ResponseBody
    @RequiresPermissions("study:exam:studyExam:update")
    public RespBody earlyTermination(@RequestBody StudyExamDto dto){
        //效验数据
        studyExamService.updateStatus(dto.getId(),ExamStatusEnum.EARLY_FINISH.getCode());
        return RespBody.data("操作成功");
    }

    /**
     * 试卷管理保存
     * @param studyExamDto 试卷管理实体类
     * @return
     */
    @CastleLog(operLocation="试卷复制",operType = OperationTypeEnum.INSERT)
    @ApiOperation("试卷复制")
    @PostMapping("/study/exam/studyExam/copy")
    @ResponseBody
    @RequiresPermissions("study:exam:studyExam:copy")
    public RespBody<String> copyStudyExam(@RequestBody StudyExamDto studyExamDto){
        if(studyExamDto == null || studyExamDto.getId() == null){
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        StudyExamEntity studyExamEntity = studyExamService.getById(studyExamDto.getId());
        studyExamEntity.setId(null);
        studyExamEntity.setExamName(studyExamEntity.getExamName()+"_复制");
        studyExamEntity.setCreateTime(new Date());
        //定时发布取消
        studyExamEntity.setQuartzTime(null);
        //7天后开始，持续7天
        Date today = new Date();
        studyExamEntity.setExamStartTime(DateUtil.offsetDay(today,7));
        studyExamEntity.setExamEndTime(DateUtil.offsetDay(today,14));
        //状态设为草稿
        studyExamEntity.setStatus(ExamStatusEnum.DRAFT.getCode());
        if(studyExamService.save(studyExamEntity)){
            //保存考试对象
            MemberAuthorityDto memberAuthorityDto = new MemberAuthorityDto();
            memberAuthorityDto.setType(AuthorityTypeEnum.EXAM.getCode());
            memberAuthorityDto.setImposeId(studyExamDto.getId());
            List<MemberAuthorityDto> dtos = memberAuthorityService.listMemberAuthority(memberAuthorityDto);
            if(dtos!=null && dtos.size()>0){
                MemberAuthorityDto authorityDto = dtos.get(0);
                authorityDto.setId(null);
                authorityDto.setImposeId(studyExamEntity.getId());
                memberAuthorityService.save(ConvertUtil.transformObj(authorityDto, MemberAuthorityEntity.class));
            }
            //保存考试题目
            QueryWrapper<StudyExamQuestionEntity> questionWrapper = new QueryWrapper<>();
            questionWrapper.eq("exam_id",studyExamDto.getId());
            List<StudyExamQuestionEntity> questionEntities = studyExamQuestionService.list(questionWrapper);
            for(StudyExamQuestionEntity entity:questionEntities){
                entity.setExamId(studyExamEntity.getId());
                entity.setId(null);
            }
            studyExamQuestionService.saveBatch(questionEntities);
            return RespBody.data("保存成功");
        }else{
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }


}
